package com.rightsidetech.system.service.impl;

import com.alibaba.dubbo.rpc.RpcContext;
import com.rightsidetech.commom.base.ResponseData;
import com.rightsidetech.commom.enums.CodeIdEnum;
import com.rightsidetech.commom.push.AgentPushUtil;
import com.rightsidetech.commom.push.Device;
import com.rightsidetech.commom.push.EnumMsgType;
import com.rightsidetech.commom.push.PushModel;
import com.rightsidetech.commom.utils.DateUtil;
import com.rightsidetech.commom.utils.StringUtil;
import com.rightsidetech.system.dtos.request.*;
import com.rightsidetech.system.dtos.request.store.StoreAppBackReq;
import com.rightsidetech.system.dtos.response.LoginAddResp;
import com.rightsidetech.system.dtos.response.LoginResp;
import com.rightsidetech.system.entity.*;
import com.rightsidetech.system.mapper.*;
import com.rightsidetech.system.service.SysAgentLoginService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Author: yhr
 * @Date: 2021-10-28 14:45
 */
@Slf4j
@Service("sysAgentLoginServiceImpl")
public class SysAgentLoginServiceImpl implements SysAgentLoginService {
    @Resource
    private SysAgentLoginInfoMapper sysAgentLoginInfoMapper;

    @Resource
    private SysAgentLoginHistoryMapper sysAgentLoginHistoryMapper;

    @Resource
    private SysAgentInfoMapper sysAgentInfoMapper;

    @Resource
    private SysAgentRoleMapper sysAgentRoleMapper;

    @Resource
    private SysAgentRoleAccountMapper sysAgentRoleAccountMapper;


    private final List<Byte> tagList = Arrays.asList((byte)1, (byte)2);


    @Override
    public ResponseData<LoginResp> loginAdmin(LoginAdminReq req,String ip) {
        LoginReq loginReq = new LoginReq();
        loginReq.setLoginName(req.getLoginName());
        loginReq.setPassword(req.getPassword());
        loginReq.setDeviceType((byte) 0);
        return login(loginReq,ip);
    }

    @Override
    public ResponseData<LoginAddResp> loginApp(LoginAppReq loginReq,String ip) {
        LoginAddResp loginResponse = new LoginAddResp();
        SysAgentLoginHistory sysAgentLoginHistory = null;
        SysAgentLoginInfo sysAgentLoginInfo = null;
        try {
            sysAgentLoginInfo = sysAgentLoginInfoMapper.selectNameOrMobile(loginReq.getLoginName());
            //获取此次登录输入密码的md5值
            if (StringUtil.isNullorEmpty(sysAgentLoginInfo)){
                return ResponseData.fail("未找到此账户，请确认是否正确");
            }
            if (sysAgentLoginInfo.getStatus() == -1){
                return ResponseData.fail("此账号已被禁用，无法登录");
            }
            SysAgentRoleAccount sysAgentRoleAccount = sysAgentRoleAccountMapper.selectByLoginId(sysAgentLoginInfo.getId());
            if (ObjectUtils.isEmpty(sysAgentRoleAccount)){
                return ResponseData.fail("帐号未绑定角色，无法登录");
            }
            SysAgentRole agentRole = sysAgentRoleMapper.selectByPrimaryKey(sysAgentRoleAccount.getRoleId());
            if (ObjectUtils.isEmpty(agentRole)){
                return ResponseData.fail("帐号未绑定角色，无法登录");
            }
            if (!agentRole.getName().equals("送货员")){
                agentRole.setName("代理商");
            }
            SysAgentInfo sysAgentInfo = sysAgentInfoMapper.selectByPrimaryKey(sysAgentLoginInfo.getAgentInfoId());
            if (ObjectUtils.isEmpty(sysAgentInfo)){
                return ResponseData.fail(CodeIdEnum.NOAGENT);
            }
            if (sysAgentInfo.getStatus() == -1){
                return ResponseData.fail("代理商已停止营业，无法登录");
            }

            String md5DigestAsHex = StringUtils.isEmpty(loginReq.getPassword()) ? null : DigestUtils.md5DigestAsHex((loginReq.getPassword() + sysAgentLoginInfo.getSalt()).getBytes());
            if (!md5DigestAsHex.equals(sysAgentLoginInfo.getPassword())) {
                sysAgentLoginHistory = historyParams((byte) -1);
                sysAgentLoginHistory.setLoginInfoId(sysAgentLoginInfo.getId());
                sysAgentLoginHistory.setLoginIp(ip);
                sysAgentLoginHistoryMapper.insertSelective(sysAgentLoginHistory);
                return ResponseData.fail("密码或账户名不正确");
            }
            SysAgentLoginHistory history = null;
            if (loginReq.getDeviceType() == 1 || loginReq.getDeviceType() == 2){
                history = sysAgentLoginHistoryMapper.selectMaxIdByDeviceTag(sysAgentLoginInfo.getId(), (byte) 1, (byte)2);
            }else {
                history = sysAgentLoginHistoryMapper.selectMaxIdByDeviceTag(sysAgentLoginInfo.getId(), loginReq.getDeviceType(), (byte)0);
            }
            SysAgentLoginHistory history2 = new SysAgentLoginHistory();
            SysAgentLoginHistory historyDate = null;
            if (!ObjectUtils.isEmpty(history)){
                history2.setEffectiveTime(history.getEffectiveTime());
                if (history.getLogoutTime() == null) {
                    Date date = new Date();
                    history.setEffectiveTime(date);
                    history.setLogoutTime(date);
                    history.setLoginInfoId(sysAgentLoginInfo.getId());
                    history.setToken(null);
                    sysAgentLoginHistoryMapper.updateBatch(history);
                }
            }
            historyDate = historyParam(sysAgentLoginInfo.getId(),loginReq.getDeviceId(),loginReq.getDeviceType(),(byte) 0);
            historyDate.setLoginIp(ip);
            sysAgentLoginHistoryMapper.insertSelective(historyDate);
            loginResponse.setLoginName(loginReq.getLoginName());
            loginResponse.setRealName(sysAgentLoginInfo.getUserName());
            loginResponse.setToken(historyDate.getToken());
            loginResponse.setRoleName(agentRole.getName());

            if (history != null &&(history.getDeviceTag() == 1 || history.getDeviceTag() == 2)
                    && !StringUtils.isEmpty(history.getDeviceId())) {
                if (!history.getDeviceId().equals(loginReq.getDeviceId())) {
                    if(!StringUtils.isEmpty(history2) && !StringUtils.isEmpty(history2.getEffectiveTime()) && System.currentTimeMillis() <= history2.getEffectiveTime().getTime()){
                        loginOutPush(history.getDeviceId(), history.getDeviceTag(), sysAgentLoginInfo.getId().toString(), EnumMsgType.APP_LOGIN_OUT.getName(), EnumMsgType.APP_LOGIN_OUT.getValue());
                        log.info("推送---给被退出设备通知成功");
                    }
                }
            }
            return ResponseData.success(loginResponse);

        } catch (Exception e) {
            log.info("登录错误：调用方法：login",e);
            throw new RuntimeException("登录失败");
        }
    }
    private ResponseData<LoginResp> login(LoginReq loginReq,String ip){
        LoginResp loginResponse = new LoginResp();
        SysAgentLoginHistory sysAgentLoginHistory = null;
        SysAgentLoginInfo sysAgentLoginInfo = null;
        try {
            sysAgentLoginInfo = sysAgentLoginInfoMapper.selectNameOrMobile(loginReq.getLoginName());
            //获取此次登录输入密码的md5值
            if (StringUtil.isNullorEmpty(sysAgentLoginInfo)){
                return ResponseData.fail("未找到此账户，请确认是否正确");
            }
            if (sysAgentLoginInfo.getStatus() == -1){
                return ResponseData.fail("此账号已被禁用，无法登录");
            }
            SysAgentInfo sysAgentInfo = sysAgentInfoMapper.selectByPrimaryKey(sysAgentLoginInfo.getAgentInfoId());
            if (ObjectUtils.isEmpty(sysAgentInfo)){
                return ResponseData.fail(CodeIdEnum.NOAGENT);
            }
            if (sysAgentInfo.getStatus() == -1){
                return ResponseData.fail("代理商已停止营业，无法登录");
            }

            String md5DigestAsHex = StringUtils.isEmpty(loginReq.getPassword()) ? null : DigestUtils.md5DigestAsHex((loginReq.getPassword() + sysAgentLoginInfo.getSalt()).getBytes());
            if (!md5DigestAsHex.equals(sysAgentLoginInfo.getPassword())) {
                sysAgentLoginHistory = historyParams((byte) -1);
                sysAgentLoginHistory.setLoginInfoId(sysAgentLoginInfo.getId());
                sysAgentLoginHistory.setLoginIp(ip);
                sysAgentLoginHistoryMapper.insertSelective(sysAgentLoginHistory);
                return ResponseData.fail("密码或账户名不正确");
            }
            SysAgentLoginHistory history = null;
            if (loginReq.getDeviceType() == 1 || loginReq.getDeviceType() == 2){
                history = sysAgentLoginHistoryMapper.selectMaxIdByDeviceTag(sysAgentLoginInfo.getId(), (byte) 1, (byte)2);
            }else {
                history = sysAgentLoginHistoryMapper.selectMaxIdByDeviceTag(sysAgentLoginInfo.getId(), loginReq.getDeviceType(), (byte)0);
            }
            SysAgentLoginHistory historyDate = null;
            if (!ObjectUtils.isEmpty(history)){
                if (history.getLogoutTime() == null) {
                    Date date = new Date();
                    history.setEffectiveTime(date);
                    history.setLogoutTime(date);
                    history.setLoginInfoId(sysAgentLoginInfo.getId());
                    history.setToken(null);
                    sysAgentLoginHistoryMapper.updateBatch(history);
                }
            }
            historyDate = historyParam(sysAgentLoginInfo.getId(),loginReq.getDeviceId(),loginReq.getDeviceType(),(byte) 0);
            historyDate.setLoginIp(ip);
            sysAgentLoginHistoryMapper.insertSelective(historyDate);
            loginResponse.setLoginName(loginReq.getLoginName());
            loginResponse.setRealName(sysAgentLoginInfo.getUserName());
            loginResponse.setToken(historyDate.getToken());

            if (history != null &&(history.getDeviceTag() == 1 || history.getDeviceTag() == 2)
                    && !StringUtils.isEmpty(history.getDeviceId())) {
                if (!history.getDeviceId().equals(loginReq.getDeviceId())) {
                    loginOutPush(history.getDeviceId(), history.getDeviceTag(), sysAgentLoginInfo.getId().toString(), EnumMsgType.APP_LOGIN_OUT.getName(), EnumMsgType.APP_LOGIN_OUT.getValue());
                    log.info("推送---给被退出设备通知成功");
                }
            }
            return ResponseData.success(loginResponse);

        } catch (Exception e) {
            log.info("登录错误：调用方法：login",e);
            throw new RuntimeException("登录失败");
        }
    }

    private SysAgentLoginHistory historyParam(Long loginId, String deviceId,Byte type, Byte status) throws Exception {
        Date date = new Date();
        SimpleDateFormat ft = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat fm = new SimpleDateFormat ("yyyy-MM-dd 02:00:00");
        SysAgentLoginHistory historyDate = new SysAgentLoginHistory();
        String token = UUID.randomUUID().toString().replace("-", "");
        historyDate.setLoginTime(date);
        historyDate.setEffectiveTime(DateUtil.addDate(ft.parse(fm.format(date)), 14));
        historyDate.setLoginInfoId(loginId);
        historyDate.setToken(token);
        historyDate.setDeviceId(deviceId);
        historyDate.setDeviceTag(type);
        //非常用地址ip登录
        historyDate.setStatus(status);
        historyDate.setLoginIp(RpcContext.getContext().getRemoteAddress().toString());
        return historyDate;
    }


    @Override
    public ResponseData<LoginAddResp> loginCode(LoginCodeReq loginReq,String ip) throws Exception {
        LoginAddResp loginResponse = new LoginAddResp();
        SysAgentLoginInfo sysAgentLoginInfo = null;
        sysAgentLoginInfo = sysAgentLoginInfoMapper.selectByMobileNo(loginReq.getPhoneNo());
        if (StringUtil.isNullorEmpty(sysAgentLoginInfo)){
            return ResponseData.fail("未找到此账户，请确认是否正确");
        }
        SysAgentInfo sysAgentInfo = sysAgentInfoMapper.selectByPrimaryKey(sysAgentLoginInfo.getAgentInfoId());
        if(StringUtil.isNullorEmpty(sysAgentInfo)){
            return  ResponseData.fail(CodeIdEnum.NOAGENT);
        }
        if(sysAgentInfo.getStatus() == -1){
            return  ResponseData.fail(CodeIdEnum.AGENTSTOP);
        }

        if (sysAgentLoginInfo.getStatus() == -1){
            return ResponseData.fail(CodeIdEnum.AGENTACCOUNTSTOP);
        }
        SysAgentRoleAccount sysAgentRoleAccount = sysAgentRoleAccountMapper.selectByLoginId(sysAgentLoginInfo.getId());
        if (ObjectUtils.isEmpty(sysAgentRoleAccount)){
            return ResponseData.fail("帐号未绑定角色，无法登录");
        }
        SysAgentRole agentRole = sysAgentRoleMapper.selectByPrimaryKey(sysAgentRoleAccount.getRoleId());
        if (ObjectUtils.isEmpty(agentRole)){
            return ResponseData.fail("帐号未绑定角色，无法登录");
        }
        if (!agentRole.getName().equals("送货员")){
            agentRole.setName("代理商");
        }
        SysAgentLoginHistory loginHistory = sysAgentLoginHistoryMapper.selectMaxIdByDeviceTag(sysAgentLoginInfo.getId(), (byte) 1, (byte)2);

        Date date = new Date();
        // 原登录记录置为过期
        if (!ObjectUtils.isEmpty(loginHistory)){
            if (loginHistory.getLogoutTime() == null) {
                loginHistory.setEffectiveTime(date);
                loginHistory.setLogoutTime(date);
                loginHistory.setLoginInfoId(sysAgentLoginInfo.getId());
                loginHistory.setToken(null);
                sysAgentLoginHistoryMapper.updateBatch(loginHistory);
            }
        }

        SysAgentLoginHistory historyDate = historyParam(sysAgentLoginInfo.getId(),loginReq.getDeviceId(),loginReq.getDeviceType(),(byte) 0);
        historyDate.setLoginIp(ip);
        sysAgentLoginHistoryMapper.insertSelective(historyDate);
        loginResponse.setLoginName(sysAgentLoginInfo.getLoginName());
        loginResponse.setRealName(sysAgentLoginInfo.getUserName());
        loginResponse.setToken(historyDate.getToken());
        loginResponse.setRoleName(agentRole.getName());

        if (loginHistory != null && (loginHistory.getDeviceTag() == 1 || loginHistory.getDeviceTag() == 2)
                && !StringUtils.isEmpty(loginHistory.getDeviceId())) {
            if (!loginHistory.getDeviceId().equals(loginReq.getDeviceId())) {
                loginOutPush(loginHistory.getDeviceId(), loginHistory.getDeviceTag(), sysAgentLoginInfo.getId().toString(), EnumMsgType.APP_LOGIN_OUT.getName(), EnumMsgType.APP_LOGIN_OUT.getValue());
                log.info("推送---给被退出设备通知成功");
            }
        }

        return ResponseData.success(loginResponse);
    }

    private SysAgentLoginHistory historyParams(Byte status) throws Exception {
        Date date = new Date();
        SimpleDateFormat ft = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat fm = new SimpleDateFormat ("yyyy-MM-dd 02:00:00");
        SysAgentLoginHistory historyDate = new SysAgentLoginHistory();
        historyDate.setLoginTime(date);
        historyDate.setEffectiveTime(DateUtil.addDate(ft.parse(fm.format(date)), 14));
        //非常用地址ip登录
        historyDate.setStatus(status);
        historyDate.setLoginIp(RpcContext.getContext().getRemoteAddress().toString());
        return historyDate;
    }

    @Override
    public ResponseData logout(String token) {
        try {
            //更新loginInfo表置空token
            SysAgentLoginHistory historyData = sysAgentLoginHistoryMapper.selectToken(token);
            if (StringUtil.isNullorEmpty(historyData)){
                return ResponseData.fail(CodeIdEnum.NotLoggedIn);
            }
            if (!StringUtils.isEmpty(historyData.getLogoutTime())){
                return ResponseData.fail(CodeIdEnum.NotLoggedIn);
            }else if (new Date().after (historyData.getEffectiveTime())){
                return ResponseData.fail(CodeIdEnum.NotLoggedIn);
            }
            historyData.setLogoutTime(new Date());
            historyData.setEffectiveTime(historyData.getLogoutTime());
            historyData.setToken(null);
            sysAgentLoginHistoryMapper.updateBatch(historyData);
            return ResponseData.success();
        }catch (Exception e){
            log.info("退出登录失败,失败方法：logout");
            return ResponseData.fail("退出登录失败");
        }
    }

    @Override
    public ResponseData updatePwd(UpdatePasswordReq req) {
        SysAgentLoginHistory history = sysAgentLoginHistoryMapper.selectToken(req.getToken());
        if (StringUtil.isNullorEmpty(history)){
            return ResponseData.fail(CodeIdEnum.NOLOGINACCOUNT);
        }
        SysAgentLoginInfo agentLoginInfo = sysAgentLoginInfoMapper.selectByPrimaryKey(history.getLoginInfoId());
        agentLoginInfo.setSalt(String.valueOf(Math.random() * 900000 + 100000));
        agentLoginInfo.setPassword(DigestUtils.md5DigestAsHex((req.getPassword() + agentLoginInfo.getSalt()).getBytes()));
        sysAgentLoginInfoMapper.updateByPrimaryKeySelective(agentLoginInfo);
        sysAgentLoginHistoryMapper.tokenNull(req.getToken());
        return ResponseData.success();
    }

    @Override
    public ResponseData register(RegisterReq req) {
        List<Long> longList = sysAgentLoginInfoMapper.selectNameMobile(null, req.getPhoneNo());
        if (!ObjectUtils.isEmpty(longList) || longList.size() > 0){
            return ResponseData.fail("系统中已存在帐号或手机号");
        }
        SysAgentLoginInfo agentLoginInfo = new SysAgentLoginInfo();
        agentLoginInfo.setLoginName(req.getPhoneNo());
        agentLoginInfo.setSalt(String.valueOf(Math.random() * 900000 + 100000));
        agentLoginInfo.setPassword(DigestUtils.md5DigestAsHex((req.getPassword() + agentLoginInfo.getSalt()).getBytes()));
        agentLoginInfo.setAgentInfoId((long) 0);
        agentLoginInfo.setMobileNo(req.getPhoneNo());
        agentLoginInfo.setIsAgent((byte) 1);
        agentLoginInfo.setCreaterName(" ");
        agentLoginInfo.setCreatedAt(new Date());
        sysAgentLoginInfoMapper.insertSelective(agentLoginInfo);
        return ResponseData.success();
    }

    @Override
    public ResponseData back(StoreAppBackReq req) {
        SysAgentLoginInfo agentLoginInfo = sysAgentLoginInfoMapper.selectByMobileNo(req.getPhoneNo());
        if(ObjectUtils.isEmpty(agentLoginInfo)){
            return ResponseData.fail(CodeIdEnum.NOACCOUNT);
        }
        SysAgentInfo sysAgentInfo = sysAgentInfoMapper.selectByPrimaryKey(agentLoginInfo.getAgentInfoId());
        if(StringUtil.isNullorEmpty(sysAgentInfo)){
            return  ResponseData.fail(CodeIdEnum.NOAGENT);
        }
        if(sysAgentInfo.getStatus() == -1){
            return  ResponseData.fail(CodeIdEnum.AGENTSTOP);
        }
        if(agentLoginInfo.getStatus() == -1){
            return ResponseData.fail(CodeIdEnum.AGENTACCOUNTSTOP);
        }

        SysAgentLoginInfo loginInfo = new SysAgentLoginInfo();
        loginInfo.setId(agentLoginInfo.getId());
        loginInfo.setSalt(String.valueOf(Math.random() * 900000 + 100000));
        loginInfo.setPassword(DigestUtils.md5DigestAsHex((req.getPassWord() + loginInfo.getSalt()).getBytes()));
        sysAgentLoginInfoMapper.updateByPrimaryKeySelective(loginInfo);

        sysAgentLoginHistoryMapper.tokenNullById(loginInfo.getId());

        SysAgentLoginHistory loginHistory = sysAgentLoginHistoryMapper.selectMaxIdByLoginInfoId(loginInfo.getId());
        Date date = new Date();
        if (loginHistory != null
                && loginHistory.getLogoutTime() == null) {
            SysAgentLoginHistory history = new SysAgentLoginHistory();
            history.setEffectiveTime(date);
            history.setLogoutTime(date);
            history.setLoginInfoId(loginHistory.getLoginInfoId());
            sysAgentLoginHistoryMapper.updateBatch(history);
        }
        return ResponseData.success("密码修改成功,请重新登录");
    }

    /**
     * 推送消息
     * @param deviceId
     * @param deviceTag
     * @param accountId
     * @param text
     * @param type
     */
    private void loginOutPush(String deviceId, Byte deviceTag, String accountId, String text, Byte type) {
        PushModel model = new PushModel();
        model.setTitle("超威云商代理商端");
        model.setText(text);
        model.setUnReadNum(1);
        model.setStringId(accountId);
        model.setPushType(type);
        Device device = new Device();
        device.setDeviceId(deviceId);
        device.setDeviceType(deviceTag.intValue());
        device.setRiderId(accountId);
        try {
            AgentPushUtil.pushToSingle(device, model);
            log.info(text + "推送成功");
        } catch (Exception e) {
            log.error(text + "推送失败", e);
        }
    }

    @Override
    public LoginResp selectById(String id) {
        return sysAgentLoginHistoryMapper.selectAgentToken(id);
    }
}
